package com.song.boot.springstudy.ms.szjz.al5;

import lombok.Data;
import lombok.ToString;
import org.apache.commons.lang3.time.StopWatch;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.stream.Collectors;

public class PriceFetcher_01 {
    // 线程池大小设为5，匹配第三方接口每秒处理5个请求的能力
    private static final ExecutorService executor = Executors.newFixedThreadPool(5);
    private static final Random random = new Random();

    public static List<PackData> fetchPrices(List<Long> times) throws InterruptedException, ExecutionException {
        // 创建用于存储所有异步任务的列表
        List<CompletableFuture<PackData>> futures = new ArrayList<>();

        // 为每个时间参数创建一个异步任务
        for (int i = 0; i < times.size(); i++) {
            int index = i;
            long time = times.get(i);
            // supplyAsync 支持返回值的
            CompletableFuture<PackData> future = CompletableFuture.supplyAsync(() -> {
                try {
                    long startTime = System.currentTimeMillis();
                    double price = callThirdPartyAPI(time);
                    long endTime = System.currentTimeMillis();
                    PackData data = new PackData();
                    data.setIndex(index);
                    data.setData(price);
                    data.setMs(endTime - startTime);
                    data.setSuccess(true);
                    return data;
                } catch (Exception e) {
                    PackData data = new PackData();
                    data.setIndex(index);
                    data.setSuccess(false);
                    return data;
                }
            }, executor);
            futures.add(future);
        }

        // 将所有CompletableFuture组合成一个
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0])
        );

        try {
            // 等待所有任务完成或5秒超时
            allFutures.get(5, TimeUnit.SECONDS);
        } catch (TimeoutException e) {
            // 超时异常不做处理，继续收集已完成的结果
        }

        // 收集所有已完成的结果
        List<PackData> results = futures.stream()
                .filter(CompletableFuture::isDone)
                .map(future -> {
                    try {
                        return future.get();
                    } catch (Exception e) {
                        return null;
                    }
                })
                .filter(data -> data != null && data.isSuccess())
                .collect(Collectors.toList());

        return results;
    }

    // 模拟第三方API调用
    private static double callThirdPartyAPI(long time) throws InterruptedException {
        // 模拟网络延迟 (100ms ~ 4099ms)
        int delay = 100 + random.nextInt(4000);
        Thread.sleep(delay);

        // 生成随机价格作为模拟结果
        return Double.parseDouble(String.format("%.2f", random.nextDouble() * 100));
    }

    public static void main(String[] args) {
        try {
            PriceFetcher_01 fetcher = new PriceFetcher_01();

            // 创建10个时间参数
            List<Long> times = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                times.add(System.currentTimeMillis() + i * 1000);
            }

            StopWatch stopWatch = StopWatch.createStarted();
            List<PackData> results = fetcher.fetchPrices(times);
            stopWatch.stop();

            System.out.println("执行时间: " + stopWatch.getTime() + " 毫秒");
            System.out.println("成功获取 " + results.size() + " 个价格:");
            results.forEach(System.out::println);

            executor.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    @Data
    @ToString
    static class PackData {
        private int index;
        private double data;
        private long ms;
        private boolean success;
    }
}
